package com.zxy.allSearcher.controller;

import com.zhipu.oapi.service.v4.model.ModelData;
import com.zxy.allSearcher.common.BaseResponse;
import com.zxy.allSearcher.common.ErrorCode;
import com.zxy.allSearcher.common.ResultUtils;
import com.zxy.allSearcher.constant.CommonConstant;
import com.zxy.allSearcher.constant.PromptConstant;
import com.zxy.allSearcher.datasource.AllDataSource;
import com.zxy.allSearcher.exception.BusinessException;
import com.zxy.allSearcher.exception.ThrowUtils;
import com.zxy.allSearcher.manager.AiManager;
import com.zxy.allSearcher.manager.SearchFacade;
import com.zxy.allSearcher.model.dto.search.SearchTextRequest;
import com.zxy.allSearcher.model.vo.SearchVO;
import com.zxy.allSearcher.service.PostService;
import com.zxy.allSearcher.utils.PageUtils;
import io.reactivex.Flowable;
import io.reactivex.schedulers.Schedulers;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 聚合接口
 */
@RestController
@RequestMapping("/search")
@Slf4j
public class SearchController {
    @Resource
    private SearchFacade searchFacade;
    @Resource
    private PostService postService;
    @Resource
    private AiManager aiManager;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    /*@Resource
    private AllDataSource allDataSource;*/

    /**
     * 分页检索（封装类）
     */
    @PostMapping("/all")
    public BaseResponse<SearchVO> searchAll(@RequestBody SearchTextRequest searchTextRequest, HttpServletRequest req) {
        // 请求合法验证
        if (searchTextRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        String searchText = searchTextRequest.getSearchText();
        /*long current = searchTextRequest.getCurrent();
        long size = searchTextRequest.getPageSize();
        return ResultUtils.success(allDataSource.doSearch(searchText,current,size));*/
        return ResultUtils.success(searchFacade.searchAll(searchTextRequest, req));
    }

    /**
     * Ai 检索
     */
    @GetMapping("/ai")
    public SseEmitter aiSearch(String searchText) {
        searchText = searchText.trim(); // 清除无用空格,根据key搜索
        if ("".equals(searchText)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 建立链接对象，0-永不超时
        SseEmitter sseE = new SseEmitter(0L);
        // 流式数据
        Flowable<ModelData> modelDataFlowable = aiManager.doStreamReq(PromptConstant.QUESTION_PROMPT, searchText, aiManager.goodTem);
        modelDataFlowable
                .observeOn(Schedulers.io())
                .map(modelData -> modelData.getChoices().get(0).getDelta().getContent())
                .flatMap(msg -> {
                    ArrayList<Character> charList = new ArrayList<>();
                    for (char c : msg.toCharArray()) {
                        charList.add(c);
                    }
                    return Flowable.fromIterable(charList);
                })
                .doOnNext(sseE::send)
                .doOnError((e) -> log.error("sse error", e))
                .doOnComplete(sseE::complete) // 通知传输完毕
                .subscribe();
        return sseE;

    }

    /**
     * 搜索建议-相同信息提示
     *
     * @param keywords 搜索词
     */
    @GetMapping("/kesWord")
    public BaseResponse<List<String>> searchSuggest(String keywords) {
        ThrowUtils.throwIf(StringUtils.isBlank(keywords), ErrorCode.PARAMS_ERROR);

        List<String> searchSuggest = postService.searchPostSuggest(keywords);
        return ResultUtils.success(searchSuggest);
    }

    /**
     * 热词
     *  redis vs LRU
     */
    @GetMapping("/hot")
    public BaseResponse<List<String>> hotWord() {
        Set<Object> searches = stringRedisTemplate.opsForHash().keys(CommonConstant.HOT_KEY);
        ArrayList<Object> searchList = new ArrayList<>(searches);
        List<String> s = searchList.stream().map(String::valueOf).collect(Collectors.toList());
        return ResultUtils.success(s);
    }
}
